#ifndef grf_TWindow_H
#define grf_TWindow_H

#include "grf_TDC.h"
#include "svl_TStackPtrFix.h"

namespace grf {

///////////////////////////////////////////////////////////////////////////////
struct TWindow;
///////////////////////////////////////////////////////////////////////////////
/*************************
struct THWindow : public TDebug
{
  HWND Handle;
  //
  THWindow()            { Handle = NULL;}
  THWindow(HWND Handle) { this->Handle = Handle;}
  //
  THWindow &operator = (HWND Handle) { this->Handle = Handle; return *this;}
  //
  operator HWND() { return Handle;}
  //
  TPoint ClientToScreen(TPoint PtClient)
  {
    POINT Pt; Pt.x = PtClient.X; Pt.y = PtClient.Y;
    ::ClientToScreen(Handle,&Pt); return Pt;
  }
  //
  void MoveWindow(TRect Rect,bool Repaint)
  {
    ::MoveWindow(Handle,Rect.Left,Rect.Top,Rect.Width,Rect.Height,Repaint);
  }
  void MoveWindow(int L,int T,int W,int H,bool Repaint)
  {
    ::MoveWindow(Handle,L,T,W,H,Repaint);
  }
  void InvalidateRect(TRect &Rect,bool BkErase = false)
  {
    ::InvalidateRect(Handle,&(::RECT)Rect,BkErase);
  }
  TRect GetWindowRect() { RECT R; ::GetWindowRect(Handle,&R); return R;}
  TRect GetClientRect() { RECT R; ::GetClientRect(Handle,&R); return R;}
};
*************************/
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

struct TShift : public svl::TSet
{
  enum EShift { Shift,Alt,Ctrl, Left,Right,Middle,Double};
  //
  svlTSet(TShift,EShift);
  //
  //void operator = (Classes::TShiftState V);
};

///////////////////////////////////////////////////////////////////////////////

struct TMouse
{
  enum EState
  {
    EState_Move,
    EState_LButtonDown,EState_LButtonUp,EState_LButtonDblClick,
    EState_RButtonDown,EState_RButtonUp,EState_RButtonDblClick
  };
  EState State;
  TShift Shift;
  TPoint PtClient;
};

///////////////////////////////////////////////////////////////////////////////

struct TMouseWheel
{
  bool   IsProcessed;
  int    Delta;
  TPoint PtClient;
  TShift Shift;
  //
  TMouseWheel() { IsProcessed = false; }
};

///////////////////////////////////////////////////////////////////////////////

struct TPaint
{
  TPaintDC          DC;
//Gdiplus::Graphics Graphics;
  //
  TPaint(TWindow &Window);
};

///////////////////////////////////////////////////////////////////////////////

struct TKeyboardKey
{
  enum EState { EState_Down,EState_Up };
  //
  bool   IsProcessed;
  EState State;
  TShift Shift;
  int    Key;
  //
  TKeyboardKey() { 
    IsProcessed = false; 
  }
};

///////////////////////////////////////////////////////////////////////////////

struct TKeyboardChar
{
  bool IsProcessed;
  char Key;
  //
  TKeyboardChar() { 
    IsProcessed = false; 
  }
};

///////////////////////////////////////////////////////////////////////////////

struct TWindow : public svl::TWindow ,public svl::TArray_Object
{
/*******
  struct TType : public svl::TNode<TWindow>::TType { virtual TType &Type() { static TType T; return T;} };
  virtual TType &Type() { return TType().Type();}
*********/
  TWindow(/*TWindow *Parent = NULL,bool EnDelete = false*/);
 ~TWindow();
  
  //virtual void Children_AddLast(TWindow *Add,bool EnDelete = true) 
  //{ 
  //  svl::TNode<TWindow>::Children_AddLast(Add,EnDelete);
  //}
  //
  operator ::HWND() { return Handle();}
  void operator = (TWindow &) { Except("operator = (TWindow &)"); }
  //
/*******************
  virtual int ShowMain();                
  virtual void Show();                
  virtual void Hide();
  virtual void ShowModal() { Igor::TWindow<ATL::CFrameWinTraits>::ShowModal();}
  bool IsModal()           { return Igor::TWindow<ATL::CFrameWinTraits>::IsModal();}
  void Close()             { ::CloseWindow(Handle());}
  //
  void SetFocus() { ::SetFocus(Handle());}
  //
  //bool IsShow()            { WindowIsVisible();}
  bool IsWindowVisible() { return ::IsWindowVisible(Handle()) != 0;}
  //
****************/  

  bool MouseIsEntered() { return mouseIsEntered;}

/*********************
  void SetCapture()     { ::SetCapture(Handle());}
  void ReleaseCapture() { if (this == GetCapture()) { ::ReleaseCapture();} }
  TWindow *GetCapture() { return Handle() == ::GetCapture() ? this : NULL;}
  //
  void SetActive() { ::SetActiveWindow(Handle());}
  bool IsActive()  { return Handle() == ::GetActiveWindow();}
*******************/  
  
  //
  TPoint ClientToScreen(TPoint PtClient);
  TPoint ScreenToClient(TPoint PtScreen);
  //
  void MoveWindow(TRect Rect,bool Repaint);
  void MoveWindow(int L,int T,int W,int H,bool Repaint);
  //
  void MoveWindowAroundClientRectTB(TSize ClientSizeThis,TWindow &WinFrom,TRect RClientFrom,bool RepaintThis);
  //
  void InvalidateRect(TRect Rect,bool BkErase = false);
  void InvalidateRect(bool BkErase = false);
  //
  void  SetWindowRect(TRect Rect,bool Repaint) { MoveWindow(Rect,Repaint);}
  TRect GetWindowRect() { ::RECT R; ::GetWindowRect(*this,&R); return R;}
  TRect GetClientRect() { ::RECT R; ::GetClientRect(*this,&R); TRect RR=R; /*RR.PTtoMM(GetScale());*/ return RR;}

protected:
  virtual void TWindow_ShowWindow(bool Show) {}
  //
  virtual void TWindow_Paint(TPaint &Paint) {}         
  virtual void TWindow_Mouse(TMouse &Mouse) {}
  virtual void TWindow_MouseWheel(TMouseWheel &Param) {}
  //                                               
  virtual void TWindow_MouseEnter() {}
  virtual void TWindow_MouseExit () {}
  //                                               
  virtual void TWindow_FocusEnter() {}
  virtual void TWindow_FocusExit () {}
  //
  virtual void TWindow_Activate(bool Active) {}
  virtual void TWindow_MouseActivate(WPARAM wParam, LPARAM lParam) {}
  //
  virtual void TWindow_KeyboardKey (TKeyboardKey  &KeyboardKey) {}
  virtual void TWindow_KeyboardChar(TKeyboardChar &KeyboardChar) {}
  //
  virtual void TWindow_AfterChangeClientSize(TSize ClientSize) {}
  //                                               
  virtual void TWindow_Close() {}

protected:
  virtual LRESULT TWindow_WndProc(TMessage &Message);
  
private:
  bool mouseIsEntered;
  //TWindowArray children;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////

struct TWindowArray
{
  int Count() { return a.Count();}
  //
  void Add(TWindow *Window,bool EnDelete) { a.Add(Window,EnDelete);}
  TWindow &Get(int N) { return *static_cast<TWindow*>(a.Get(N));}
  //
  void Hide();

private:
  svl::TArray a;
};

////////////////////////////////////////////////////////////////////////////////

struct TCaret : public TDebug
{
  TRect    RClient;
  TWindow &Window;
  //
  TCaret(TWindow &Window_) : Window(Window_) {}
 ~TCaret() { ::DestroyCaret();}
  //
  void Update()
  {
    TSize Size = RClient.Size(); //Size.MMtoPT(Window.GetScale());

    ::DestroyCaret();
    ::CreateCaret(Window,NULL,Size.Width,Size.Height);
    SetPos(RClient.LeftTop());
  }
  //
  void Destroy() { ::DestroyCaret(); RClient.Width = RClient.Height = 0; }
  //
  void Show() { ::ShowCaret(Window);}
  void Hide() { ::HideCaret(Window);}
  //
  void SetPos(TPoint PtClient) 
  { 
    RClient.SetLeftTop(PtClient); 
    //PtClient.MMtoPT(Window.GetScale());
    ::SetCaretPos(PtClient.X,PtClient.Y); 
  }
/******
  void Move(int Dx,int Dy)   
  { 
    RClient.Left += Dx; RClient.Top += Dy; 
    SetPos(RClient.LeftTop()); 
  }
**********/  
};

////////////////////////////////////////////////////////////////////////////////
}

#endif
